package org.amuthu.expression;

import org.amuthu.expression.exception.TypeMismatchException;
import org.amuthu.parser.ExpressionVisitor;

/**
 * Representation of a composite executable parse tree. Any expression
 * in the <i>Gondola</i> language is parsed into a composite structure
 * built upon this class. This class therefore represents an executable
 * expression.
 * <p>
 * Any single object of this type could represent a <b>terminal expression</b>
 * that is a number such as "<code>5</code>",
 * a <b>unary expression</b> such as "<code>not(X)</code>",
 * a <b>binary expression</b> such as "<code>X and Y</code>" or a
 * <b>ternary expression</b>. The arguments labeled above as <code>X</code>
 * and <code>Y</code> would be represented by separate <code>Expression</code>
 * classes.
 * Those classes would however be contained by this class.
 */
public interface Expression extends Cloneable
{
   /** A boolean type that can be either {@link #TRUE} or {@link #FALSE}. */
   public static final int BOOLEAN_TYPE = 0;
   /** Value of <code>FALSE</code> */
   public final static double FALSE = 0.0D;
   /** Represents a stock float quote <b>type</b>: open, close, low, high */
   public static final int FLOAT_QUOTE_TYPE = 3;
   /** A float type that can contain any number. */
   public static final int FLOAT_TYPE = 1;
   /** Represents a stock integer quote <b>type</b>: volume */
   public static final int INTEGER_QUOTE_TYPE = 4;
   /** Represents a type than can contain any short number. */
   public static final int INTEGER_SHORT_TYPE = 6;
   /** An integer type that can contain any integer number. */
   public static final int INTEGER_TYPE = 2;
   /** Represents either a float or an integer. */
   public static final int NUMERIC_TYPE = 7;
   /** Represents a string type that can contain any string. */
   public static final int STRING_TYPE = 5;
   /** Value of <code>TRUE</code> */
   public final static double TRUE = 1.0D;
   /** Threshold level where a number is registered as <code>TRUE</code> */
   public static final double TRUE_LEVEL = 0.1D;
   /** Type is undefined. Initial or default value only. Shouldn't be returned unless there's a bug. */
   public static final int UNDEFINED_TYPE = -1;

void accept(ExpressionVisitor visitor);

/**
    * Convert the given expression to a string.
    *
    * @return  the string representation of the expression
    */
   @Override
   public String toString();

   /**
    * Perform type checking on the expression.
    *
    * @return  the return type of the expression
    * @throws  TypeMismatchException if the expression has incorrect types
    */
   public int checkType() throws TypeMismatchException;

   /**
    * Get the type of the expression.
    *
    * @return one of {@link #BOOLEAN_TYPE}, {@link #FLOAT_TYPE},
    *         {@link #INTEGER_TYPE}, {@link #FLOAT_QUOTE_TYPE} or
    *         {@link #INTEGER_QUOTE_TYPE}.
    */
   public int getType();

   /**
    * Return the number of arguments of this expression.
    *
    * @return  the number of arguments
    */
   public int getChildCount();

   /**
    * Return the given argument.
    *
    * @param   index   the argument index
    * @return  the argument
    */
   public Expression getChild(int index);

   /**
    * Return the index of the given argument in the expression. We override
    * this method because we use "==" to denote equality, not "equals"
    * as the former would return the first argument with the same expression
    * not necessarily the actual expression instance desired.
    *
    * @param expression the child expression to locate
    * @return index of the child expression or <code>-1</code> if it could
    *              not be found
    */
   public int getIndex(Expression expression);

   /**
    * Count the number of nodes in the tree.
    *
    * @return number of nodes or 1 if this is a terminal node
    */
   public int size();

   /**
    * Count the number of nodes in the tree with the given type.
    *
    * @return number of nodes in the tree with the given type.
    */
   public int size(int type);

   /**
    *
    * @return true if none of the children of the expression are null
    */
   public boolean validTree();

   /**
    *
    * Print a string of all the children in a tree form.
    * @param level The depth of the tree
    * @param code A code (e.g. hashcode) of a node
    * @return A string representing the expression tree tree
    */
   public String printTree(int level, int code);

}

